/*
 * WebClientUtils.java
 *
 * Created on November 13, 2007, 12:53 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.servoy.plugins;

import com.servoy.j2db.plugins.*;
import com.servoy.j2db.scripting.IScriptObject;
import com.servoy.j2db.server.headlessclient.*;
import com.servoy.j2db.preference.PreferencePanel;

import java.beans.PropertyChangeEvent;
import java.util.Map;
import java.util.Properties;
import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.mozilla.javascript.Function;
/**
 *
 * @author Sean
 */
public class WebClientPlugin implements IClientPlugin, IScriptObject{

	private final static String CALLBACK_BEHAVIOR = "com.servoy.jscallback";
	
    private IWebClientPluginAccess app;
    private BehaviorProvider behavior;
    private Icon icon;

    //  plugin implementations
    public Icon getImage() {
        if(icon == null)
            icon = new ImageIcon(getClass().getResource("js.jpg"));
            
        return icon;
    }
    public String getName() {
        return "WebClientUtils";
    }
    public PreferencePanel[] getPreferencePanels() {
        return null;
    }
    public Properties getProperties() {
    	Properties props = new Properties();
        props.put(DISPLAY_NAME, "Web Client Utilities");
        return props;
    }
    public IScriptObject getScriptObject() {
        return this;
    }
    public void initialize(IClientPluginAccess iClientPluginAccess) throws PluginException {
        try {
System.out.println("LOADED**********");            
            //  web access
            app = (IWebClientPluginAccess)iClientPluginAccess;
            behavior = new BehaviorProvider();
            app.getPageContributor().addBehavior(CALLBACK_BEHAVIOR, behavior);
          
        }catch(ClassCastException cce){
            //  Do Nothing: this is expected - only loads in web client
        }catch(Exception e){
        	throw new PluginException("Failed to register plugin: " + e.getMessage()); 
        }
    }
    public void load() throws PluginException {
    }
    public void propertyChange(PropertyChangeEvent evt) {
    }
    public void unload() throws PluginException {
    }
    
    
    //  script implementations
    
    public Class[] getAllReturnedTypes() {
        return null;
    }
    public String[] getParameterNames(String string) {
    	
    	if("executeClientSideJS".equals(string)){
	        return new String[]{"jsToExecute", "[callbackMethod]", "[argArray]"};
    	} else if("addCallback".equals(string)){
    		return new String[]{"[callbackMethod]"};
    	}
    	return null;
    }
    
    public String getSample(String method) {
    	
    	if("executeClientSideJS".equals(method)){
    		return "// ex 1) Execute simple Client-Side Javascript (Web-Client only)\n" +
               "var jsToExecute = \"alert('Hello World: Called From Servoy Method!');\"\n" +
               "plugins.WebClientUtils.executeClientSideJS(jsToExecute)\n\n" +
                "// ex 2) Execute client-side script w/ callback\n" +
                "// Add two numbers on the client and send the result to the server." +
                "// You can send an array of literals back to the server and into a callback method." +
                "// (Literals will be evaluated on the client first)\n" +
                "var jsToExecute = \"var sum = 1 + 2\";\n" +
                "plugins.WebClientUtils.executeClientSideJS(jsToExecute, myCallBackMethod, ['sum'])\n";
    	
    	}else if("addCallback".equals(method)){
    		String str = "var callback = plugins.WebClientUtils.addCallback(myMethod, ['arg1','argN']);\n";
    		str += "var script = 'function myFunction(arg1, argN){'+callback+'}';\n";
    		str += "var markup = '<html><head><script type=\"text/javascript\">'+script+'</script></head></html>'";
    		return str;
    	}
    	
    	return null;
    }
    public String getToolTip(String method) {
    	
        if("executeClientSideJS".equals(method))
            return "Executes Client-Side Javascript with optional callback on server";
        else if("addCallback".equals(method))
        	return "Adds web-client call-back behavior for a method. Returns the javascript for the client.";
        
        return null;
    }
    public boolean isDeprecated(String string) {
        return false;
    }

    public void js_executeClientSideJS(String js){
        executeJS(js, null, null);
    }
    
    public void js_executeClientSideJS(String js, Function callback){
        executeJS(js, callback, null);
    }
    
    public void js_executeClientSideJS(String js, Function callback, String[] args){
        executeJS(js, callback, args);
    }
    public String js_addCallback(Function callback){
    	return js_addCallback(callback, null);
    }
    public String js_addCallback(Function callback, String[] args){
    	if(app != null){
	    	behavior.addCallBack(callback);
	        return behavior.getUrlForCallback(callback, args);  
    	}
    	return null;
    }
    private String executeJS(String js, Function callback, String[] args){
        if(app != null){
            
            //  no callback
            if(callback == null){
                app.getPageContributor().addDynamicJavaScript(js);
                return null;
            }
            
            //  execute w/ callback...
            behavior.addCallBack(callback);
            String get = behavior.getUrlForCallback(callback, args);          
            app.getPageContributor().addDynamicJavaScript(js + "\n" + get);
            return get;
        }
        return null;
    }
	public Map getRequiredPropertyNames() {
		return null;
	}
}
